#ifndef __NEZHA_RTTI_H__
#define __NEZHA_RTTI_H__

#pragma once

#include "EngineCompileConfig.h"

namespace Nezha
{

	/** Runtime type information. */
	class NEZHA_ENGINE_ENTRY Rtti
	{
	public:
		Rtti(const char* name, const Rtti* base);
		~Rtti();

		const char* name() const
		{
			return m_cszName;
		}

		const Rtti* base() const
		{
			return m_cpBase;
		}

		bool isDerived(const Rtti& info) const;
	private:
		const char* m_cszName;
		const Rtti* m_cpBase;
	};

	/** Runtime type information hooker. */
	class NEZHA_ENGINE_ENTRY RttiQuery
	{
	public:
		virtual ~RttiQuery(){}
	protected:
		RttiQuery(){}

	public:
		static const Rtti RunTimeTypeInfo;

		virtual const Rtti& getRunTimeTypeInfo() const
		{
			return RunTimeTypeInfo;
		}


NEZHA_INTERNAL:
		bool isExactly(const Rtti& type) const;
		bool isDerived(const Rtti& type) const;
		bool isExactlyTypeOf(const RttiQuery* obj) const;
		bool isDerivedTypeOf(const RttiQuery *obj) const;

	};

	template <class T>
	T* CuteRttiCast(RttiQuery* obj)
	{
		return obj && obj->getRunTimeTypeInfo().isDerived(T::RunTimeTypeInfo) ?
			static_cast<T*>(obj) : NULL;
	}

	template <class T>
	const T* CuteRttiCast(const RttiQuery* obj)
	{
		return obj && obj->getRunTimeTypeInfo().isDerived(T::RunTimeTypeInfo) ?
			static_cast<const T*>(obj) : NULL;
	}

#define CUTE_RTTI\
	public:\
	static const Rtti RunTimeTypeInfo;\
	virtual const Rtti& getRunTimeTypeInfo() const{\
		return RunTimeTypeInfo;\
	}

#define CUTE_RTTI_EXPORT(_export_)\
public:\
			##_export_ static const Rtti RunTimeTypeInfo;\
		   virtual const Rtti& getRunTimeTypeInfo() const{\
		   return RunTimeTypeInfo;\
	   }

#define CUTE_RTTI_IMPLEMENT(classname, base) \
	const Rtti classname::RunTimeTypeInfo(#classname, &base)

#define CUTE_RTTI_IMPLEMENT_TEMPLATE(classname,base) \
	template <> \
	const Rtti classname::RunTimeTypeInfo(#classname, &base)

}//end namespace Nezha

#endif //end __NEZHA_RTTI_H__